package com.xiaoniu.mc.hystrix;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;

import java.lang.reflect.Method;
import java.util.List;

/**
 * @类描述：
 * @创建人：林继丰
 * @创建时间：2017/9/19 14:11
 * @版权：Copyright (c) 深圳市牛鼎丰科技有限公司-版权所有.
 */
public class HystrixBeanDefinitionParser implements BeanDefinitionParser {

    @Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        String id = element.getAttribute("id");
        String targetClass = element.getAttribute("targetClass");
        String groupKey = element.getAttribute("groupKey");
        String commandKey = element.getAttribute("commandKey");
        String threadPoolKey = element.getAttribute("threadPoolKey");
        String strategy = element.getAttribute("strategy");
        String timeoutInMilliseconds = element.getAttribute("timeoutInMilliseconds");
        String circuitBreakerEnabled = element.getAttribute("circuitBreakerEnabled");
        String circuitBreakerRequestVolumeThreshold = element.getAttribute("circuitBreakerRequestVolumeThreshold");
        String fallBackClass = element.getAttribute("fallBackClass");
        String fallBackMethod = element.getAttribute("fallBackMethod");
        String accordance = element.getAttribute("accordance");
        String coreSize = element.getAttribute("coreSize");
        String maxQueueSize = element.getAttribute("maxQueueSize");

        List<Element> childElements = DomUtils.getChildElementsByTagName(element, "method");

        if (!Boolean.parseBoolean(accordance)) {
            for (Element childElement : childElements) {
                String methodName = childElement.getAttribute("name");
                String innerFallBackClass = childElement.getAttribute("fallBackClass");
                String innerFallBackMethod = childElement.getAttribute("fallBackMethod");
                String innerTimeoutInMilliseconds = childElement.getAttribute("timeoutInMilliseconds");
                String innerCircuitBreakerRequestVolumeThreshold = childElement.getAttribute("circuitBreakerRequestVolumeThreshold");
                String innerCoreSize = childElement.getAttribute("coreSize");
                String innermaxQueueSize = childElement.getAttribute("maxQueueSize");
                if (StringUtils.isBlank(methodName)) {
                    throw new RuntimeException("name不存在");
                }

                String fullMethodName = targetClass + "." + methodName;
                HystrixConfig config = new HystrixConfig();
                config.setCircuitBreakerEnabled(circuitBreakerEnabled);
                config.setCircuitBreakerRequestVolumeThreshold(circuitBreakerRequestVolumeThreshold);
                config.setCommandKey(commandKey);
                config.setCoreSize(coreSize);
                config.setFallBackClass(fallBackClass);
                config.setFallBackMethod(fallBackMethod);
                config.setGroupKey(groupKey);
                config.setCircuitBreakerEnabled(circuitBreakerEnabled);
                config.setStrategy(strategy);
                config.setThreadPoolKey(threadPoolKey);
                config.setTimeoutInMilliseconds(timeoutInMilliseconds);
                config.setMaxQueueSize(maxQueueSize);

                if (StringUtils.isNotBlank(innerCircuitBreakerRequestVolumeThreshold))
                    config.setCircuitBreakerRequestVolumeThreshold(innerCircuitBreakerRequestVolumeThreshold);

                if (StringUtils.isNotBlank(innerCoreSize))
                    config.setCoreSize(innerCoreSize);

                if (StringUtils.isNotBlank(innerFallBackMethod))
                    config.setFallBackMethod(innerFallBackMethod);

                if (StringUtils.isNotBlank(innerFallBackClass))
                    config.setFallBackClass(innerFallBackClass);

                if (StringUtils.isNotBlank(innermaxQueueSize))
                    config.setMaxQueueSize(innermaxQueueSize);

                if (StringUtils.isNotBlank(innerTimeoutInMilliseconds))
                    config.setTimeoutInMilliseconds(innerTimeoutInMilliseconds);

                FuseContext.methodNameMapConfig.put(fullMethodName, config);
            }

        } else {
            try {
                Method[] methods = Class.forName(targetClass).getDeclaredMethods();
                for (Method m : methods) {
                    String methodName = m.getName();
                    String fullMethodName = targetClass + "." + methodName;
                    HystrixConfig config = new HystrixConfig();
                    config.setCircuitBreakerEnabled(circuitBreakerEnabled);
                    config.setCircuitBreakerRequestVolumeThreshold(circuitBreakerRequestVolumeThreshold);
                    config.setCommandKey(commandKey);
                    config.setCoreSize(coreSize);
                    config.setFallBackClass(fallBackClass);
                    config.setFallBackMethod(fallBackMethod);
                    config.setGroupKey(groupKey);
                    config.setCircuitBreakerEnabled(circuitBreakerEnabled);
                    config.setStrategy(strategy);
                    config.setThreadPoolKey(threadPoolKey);
                    config.setTimeoutInMilliseconds(timeoutInMilliseconds);
                    config.setMaxQueueSize(maxQueueSize);
                    FuseContext.methodNameMapConfig.put(fullMethodName, config);
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }

        }
        return null;
    }
}
